package com.rainyun.rcmc.bukkit;

import com.rainyun.rc.command.CmdPath;
import com.rainyun.rc.command.CmdUtil;
import com.rainyun.rc.config.annotation.LangConf;
import com.rainyun.rc.ioc.RainIOC;
import com.rainyun.rc.util.RainF;
import com.rainyun.rc.util.RainFile;
import com.rainyun.rc.util.RainLoader;
import com.rainyun.rcmc.bukkit.annotation.BukPlugin;
import com.rainyun.rcmc.bukkit.config.BukYmlNode;
import com.rainyun.rcmc.mc.annotation.NmsComp;
import com.rainyun.rcmc.own.config.RcLang;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**RainCore开发一键生成工具类*/
public class BukDevTools {

    /**一键生成项目的默认元素<br>
     * 如plugin.yml(含权限配置树,nms兼容配置),语言文件等<br>
     * 参数: root根目录(默认项目下),
     * langpath(默认lang/zh-CN)*/
    public static void main(String[] args) throws IOException {
        try {
            String root = args.length>0?args[0]:"";
            BukDevTools tool = new BukDevTools(BukDevTools.class.getClassLoader(),root);
            String langpath = args.length>1?args[1]:"lang/"+ Locale.getDefault().toLanguageTag();
            //加载指令
            tool.initCmds();
            //识别主类和meta.yml生成plugin.yml
            tool.MetaToPlugins();

            //保存语言到
            tool.getLangAndSaveDefault(langpath);
            //用help属性自动配置语言文件
            tool.CmdAttrToConf("help","cmds",langpath);
        }catch (Exception e){
            e.printStackTrace();
        }
    }


    /**根目录*/
    protected String root;
    /**类加载器*/
    protected ClassLoader classLoader;
    /**项目内的所有类*/
    protected List<Class<?>> classes;
    /**已加载的指令集*/
    protected Map<String, ? extends CmdPath<?>> cmds;

    public BukDevTools(ClassLoader classLoader,String root) throws IOException {
        this.root = root;
        this.classLoader = classLoader;
        classes = RainLoader.loadFolderClasses(root+"target/classes",classLoader);
        RainIOC.load(classes);
    }
    public BukDevTools(ClassLoader classLoader) throws IOException {
        this.classLoader = classLoader;
        classes = RainLoader.loadClassesByObj(this,classLoader);
        RainIOC.load(classes);
    }

    /**加载指令集*/
    public void initCmds(){
        Map<String, ? extends CmdPath<?>> cmds = CmdUtil.getAllCmds(classes);
        CmdUtil.initAllCmdBiz(classes,cmds);
        this.cmds = cmds;
    }

    /**(常用) 作用同 {@link #CmdAttrToConf(String, String, String...)}<br>
     * 且path为资源下的相对路径,自动输出到src/main/resources/+target/classes/ */
    public void CmdAttrToConf(String attr,String node,String path){
        CmdAttrToConf(attr,node,"src/main/resources/"+path,"target/classes/"+path);
    }

    /**用指令集的属性自动设置配置,(比如help)
     * @param attr 指令属性
     * @param node 配置节点
     * @param paths 配置文件路径(无需.yml后缀) */
    public void CmdAttrToConf(String attr,String node,String... paths){
        Map<String, Object> tree = CmdUtil.getCmdAttrTree(cmds, attr);

        BukYmlNode yml = new BukYmlNode(new File(root).getAbsolutePath(), "",classLoader);
        yml.setVerCheck("tmp",false);

        for(String path:paths){
            yml.add("tmp",path);
            try {
                File f = new File(yml.getRootPath(), path+".yml");
                if(!f.exists()) RainFile.newFile(f);//创建
                yml.load("tmp");
                YamlConfiguration tmp = yml.get("tmp");
                tmp.set(node,tree);
                yml.save("tmp");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**(常用) 作用同 {@link #MetaToPlugins(String, String...)} <br>
     * 自动读取src/main/java下的meta,自动输出到src/main/resource/plugin.yml和target/classes目录*/
    public void MetaToPlugins(){
        MetaToPlugins("src/main/java/meta", "src/main/resources/plugin","target/classes/plugin");
    }

    /**一键读取插件主类和meta.yml,处理权限数+指令集+nms,生成对应需要的文件,如plugin.yml
     * @param metapath meta.yml路径,为null时即忽略文件
     * @param output 输出plugins.yml路径*/
    public void MetaToPlugins(String metapath,String ...output) {
        try {
            BukYmlNode yml = new BukYmlNode(new File(root).getAbsolutePath(), "",classLoader);
            yml.add("meta",metapath);

            File f = new File(yml.getRootPath(), metapath+".yml");
            if(!f.exists()) RainFile.newFile(f);//创建meta

            if(metapath!=null) yml.load("meta");
            else yml.set("meta",new YamlConfiguration());

            YamlConfiguration metafile = yml.get("meta");

            ConfigurationSection permtree = metafile.getConfigurationSection("permissions");
            metafile.set("permissions",null);

            YamlConfiguration cmdsconf = new YamlConfiguration();

            for(Map.Entry<String, ? extends CmdPath<?>> en:cmds.entrySet())
            {
                CmdPath<?> cmd = en.getValue();
                YamlConfiguration cmdconf = new YamlConfiguration();
                Object perm = en.getValue().getAttr("perm");
                if(perm!=null){
                    cmdconf.set("permission",perm);
                    cmdconf.set("permission-message","§c你没有权限: <permission> -w-" +
                            "\n§7(You don't have permission: <permission>)");
                }
                Object alias = cmd.getAttr("alias");
                if(alias!=null&&((String[])alias).length>0)
                    cmdconf.set("aliases",alias);
                Object help = cmd.getAttr("help");
                if(help!=null)cmdconf.set("usage",help);

                cmdsconf.set(en.getKey(),cmdconf);
            }

            List<String> tonmscomp = new ArrayList<>();
            //获取主类信息和nms兼容信息
            for(Class<?> c:classes){
                if(c.isAnnotationPresent(BukPlugin.class)){
                    metafile.set("main",c.getName());
                    BukPlugin meta = c.getAnnotation(BukPlugin.class);
                    metafile.set("name",meta.name());
                    metafile.set("author",meta.author());
                    if(!meta.version().isEmpty())
                        metafile.set("version",meta.version());
                    if(!meta.api_version().isEmpty())
                        metafile.set("api-version",meta.api_version());
                    if(!meta.mail().isEmpty())
                        metafile.set("mail",meta.mail());
                    if(!meta.website().isEmpty())
                        metafile.set("website",meta.website());
                    if(!meta.description().isEmpty())
                        metafile.set("description",meta.description());
                    if(!meta.prefix().isEmpty())
                        metafile.set("prefix",meta.prefix());
                    if(meta.contributors().length>0)
                        metafile.set("contributors",meta.contributors());
                    if(meta.depend().length>0)
                        metafile.set("depend",meta.depend());
                    if(meta.softdepend().length>0)
                        metafile.set("softdepend",meta.softdepend());
                }
                if(c.isAnnotationPresent(NmsComp.class)){
                    tonmscomp.add(c.getName().replace(".","-"));
                }
            }
            if(!tonmscomp.isEmpty()){
                metafile.set("nms_current","none");
                metafile.set("nms_class",tonmscomp);
            }

            metafile.set("commands",cmdsconf);
            // 处理权限
            Map<String, Object> permtreemap = RainBukkitUtil.getPermsfromTree(BukYmlNode.confToMap(permtree));
            metafile.set("permissions",permtreemap);

            yml.add("plugin","");
            yml.set("plugin",metafile);
            yml.setDescTree("plugin",yml.getDescTree("meta"));

            //保存
            for (String out:output){
                yml.add("plugin",out);
                yml.save("plugin");
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public void getLangAndSaveDefault(String savepath) throws IOException {
        List<Class<?>> cl = RainF.filter(classes,o->o.isEnum()&&o.isAnnotationPresent(LangConf.class));
        for(Class<?> c:cl){
            saveDefaultTo(savepath, (Class<? extends Enum<?>>) c);
        }
    }

    /**(常用) 作用同 {@link #saveDefaultTo(Class, String...)} <br>
     * 且path为资源下的相对路径,自动输出到src/main/resources/+target/classes/ */
    public void saveDefaultTo(String path,Class<? extends Enum<?>> en) throws IOException {
        saveDefaultTo(en,"src/main/resources/"+path,"target/classes/"+path);
    }

    /**保存枚举的默认值和注释到某yml配置文件
     * (配合Desc好DefString/DefInt注解)
     * @param en 枚举类
     * @param paths 配置文件路径
     * */
    public void saveDefaultTo(Class<? extends Enum<?>> en,String... paths) throws IOException {
        BukYmlNode yml = new BukYmlNode(new File(root).getAbsolutePath(), "", null);
        YamlConfiguration tree = yml.getTreeByEnum(en);
        Map<String, Object> dtree = yml.getDescTreeByEnum(en);
        yml.setVerCheck("src/src/main/resources/lang",false);
        for (String path:paths){
            yml.add("src/src/main/resources/lang",path);
            try {
                File f = new File(yml.getRootPath(), path+".yml");
                if(!f.exists()) RainFile.newFile(f);//创建
                yml.load("src/src/main/resources/lang");
            } catch (Exception e) {
                e.printStackTrace();
            }
            YamlConfiguration lang = yml.get("src/src/main/resources/lang");
            //和原配置合并
            for(String k:tree.getKeys(false))
                lang.set(k,tree.get(k));
            Map<String,Object> odt = yml.getDescTree("src/src/main/resources/lang");
            odt.putAll(dtree);
            yml.saveAll();
        }
    }

}


















